﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "PropertyComboxGroups.h"
#include "PropertyComponentTypeWidget.h"
#include "GbmpAssert.h"
#include <QListWidget>
#include <QStyledItemDelegate>
#include <QHBoxLayout>


#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"
using namespace PropertyWidget;

class ItemDelegate : public QStyledItemDelegate
{
public:
    ItemDelegate(QObject * parent=0):QStyledItemDelegate(parent){}
    virtual ~ItemDelegate(){}
    void paint(QPainter * painter,const QStyleOptionViewItem & option,const QModelIndex & index) const;
};

void ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItem itemOption(option);
    // remove the focus state
    if (itemOption.state & QStyle::State_HasFocus)
    {
        itemOption.state ^= QStyle::State_HasFocus;
    }
    QStyledItemDelegate::paint(painter, itemOption, index);
}

QComboxGroups::QComboxGroups(QWidget *parent)
    : QWidget(parent),
    m_upComboBox(nullptr)
{
    m_upComboBox = std::unique_ptr<QComboBox>(new QComboBox(this));
    m_upComboBox->blockSignals(true);
    m_upComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_upComboBox->setEditable(false);
    m_upComboBox->setObjectName("ComboBoxType");
    m_upComboBox->setItemDelegate(new ItemDelegate(this));
    m_upComboBox->setStyleSheet("QComboBox{ font-family: \"Microsoft YaHei\";}");
    connect(m_upComboBox.get(), SIGNAL(currentIndexChanged(int)), this, SLOT(OnComboBoxChanged()));

    QHBoxLayout * pLayout = new QHBoxLayout(this);  
    pLayout->setContentsMargins(0, 0, 0, 0);
    pLayout->addWidget(m_upComboBox.get());
    m_upComboBox->blockSignals(false);
}

QComboxGroups::~QComboxGroups()
{

}

bool QComboxGroups::setCurrentItem( int groupIndex,int indexInGroup)
{
    if (groupIndex < 0 || groupIndex >= (int)m_ComponentTypeGroups.size())
    {
        return false;
    }

    int curidx = GetComboBoxIndex(groupIndex, indexInGroup);
    if(curidx >= 0)
    {
        m_upComboBox->blockSignals(true);
        m_upComboBox->setCurrentIndex(curidx);
        m_upComboBox->blockSignals(false);
        return true;
    }
    else
    {
        GBMP_ASSERT(false);
    }

    return false;
}

void QComboxGroups::SetEnableComponentTypeChangeComboBox(bool isEnable)
{
    m_upComboBox->setEnabled(isEnable);
}

bool QComboxGroups::AddItemsGroup( int groupIndex,PropertyWidget::CComponentTypeGroup *componentTypeGroup )
{
    if (nullptr == componentTypeGroup || groupIndex < 0 || groupIndex > (int)m_ComponentTypeGroups.size())
    {
        return false;
    }

    auto iterFind = m_ComponentTypeItems.find(componentTypeGroup);
    if (iterFind != m_ComponentTypeItems.end())//已经有了就不能再添加
    {
        return false;
    }

    
    m_upComboBox->blockSignals(true);//信号阻塞
    if(m_ComponentTypeGroups.empty() == false)
    {
        int idx = GetComboBoxIndex(groupIndex, 0);
        m_upComboBox->insertSeparator(idx);
    }
    else
    {
        m_upComboBox->clear();
    }
    m_upComboBox->blockSignals(false);//取消信号阻塞

    TypeGroupVec::iterator itr = m_ComponentTypeGroups.begin() + groupIndex;
    m_ComponentTypeGroups.insert(itr,componentTypeGroup);
    return true;
}

bool QComboxGroups::AddItem(int groupIndex,int indexInGroup,PropertyWidget::CComponentTypeItem *cmptTypeItem )
{
    if(nullptr == cmptTypeItem || groupIndex < 0 || groupIndex >= (int)m_ComponentTypeGroups.size())
    {
        return false;
    }

    CComponentTypeGroup * pComponentTypeGroup = m_ComponentTypeGroups[groupIndex];
    std::vector<CComponentTypeItem *>& cmptTypeItems = m_ComponentTypeItems[pComponentTypeGroup];
    if (indexInGroup < 0 || indexInGroup > (int)cmptTypeItems.size())
    {
        return false;
    }

    //信号阻塞
    m_upComboBox->blockSignals(true);

    QPixmap pic(1, 32);
    pic.fill(Qt::transparent);
    QIcon icon(pic);
    m_upComboBox->setIconSize(QSize(1, 32 + 4));//上下各预留2px空间
    int idx = GetComboBoxIndex(groupIndex, indexInGroup);
    m_upComboBox->insertItem(idx, icon, cmptTypeItem->Name());
    if(m_upComboBox->isEnabled() == false)
        m_upComboBox->setEnabled(true);

    //取消信号阻塞
    m_upComboBox->blockSignals(false);

    std::vector<CComponentTypeItem *>::iterator itr = cmptTypeItems.begin() + indexInGroup;
    cmptTypeItems.insert(itr, cmptTypeItem);
    return true;
}

bool QComboxGroups::RemoveItem(int groupIndex,int indexInGroup)
{
    if (groupIndex < 0 || groupIndex >= (int)m_ComponentTypeGroups.size() )
    {
        return false;
    }

    CComponentTypeGroup *pComponentTypeGroup = m_ComponentTypeGroups[groupIndex];
    std::vector<CComponentTypeItem *>& cmptTypeItems = m_ComponentTypeItems[pComponentTypeGroup];
    if (indexInGroup < 0 || indexInGroup >= (int)cmptTypeItems.size())
    {
        return false;
    }

    //只有一个条直接删除整过组
    if(cmptTypeItems.size() == 1)
    {
        RemoveItemsGroup(groupIndex);
    }
    else
    {
        int idx = GetComboBoxIndex(groupIndex, indexInGroup);
        m_upComboBox->removeItem(idx);
    }
    
    //同步数据
    cmptTypeItems.erase(cmptTypeItems.begin() + indexInGroup);
    return true;
}

bool QComboxGroups::RemoveItemsGroup(int groupIndex)
{
    if (groupIndex < 0 || groupIndex >= (int)m_ComponentTypeGroups.size())
    {
        return false;
    }

    //信号阻塞
    m_upComboBox->blockSignals(true);

    //移除构件类型分组内部的条目
    CComponentTypeGroup * pComponentTypeGroup = m_ComponentTypeGroups[groupIndex];
    std::vector<CComponentTypeItem *> & cmptTypeItems = m_ComponentTypeItems[pComponentTypeGroup];
    for(int i = 0; i < (int)cmptTypeItems.size(); ++i)
    {
        int idx = GetComboBoxIndex(groupIndex, i);
        m_upComboBox->removeItem(idx);
    }

    //取消信号阻塞
    m_upComboBox->blockSignals(false);

    // 同步数据
    m_ComponentTypeItems.erase(pComponentTypeGroup);
    m_ComponentTypeGroups.erase(m_ComponentTypeGroups.begin() + groupIndex);
    return true;
}

bool QComboxGroups::RemoveAllItemsGroup()
{
    m_ComponentTypeGroups.clear();
    m_ComponentTypeItems.clear(); 

    //信号阻塞
    m_upComboBox->blockSignals(true);
    m_upComboBox->clear();
    //取消信号阻塞
    m_upComboBox->blockSignals(false);
    return true;
}

int QComboxGroups::GetComboBoxIndex(int groupIndex,int indexInGroup)
{
    GBMP_ASSERT(groupIndex >= 0 && groupIndex <= (int)m_ComponentTypeGroups.size() && indexInGroup >= 0 /*&& 
        indexInGroup < m_ComponentTypeItems[m_ComponentTypeGroups[groupIndex]].size()*/);

    int idx = 0;
    for(int ngroup = 0; ngroup < groupIndex; ++ngroup)
    {
        CComponentTypeGroup * pComponentTypeGroup = m_ComponentTypeGroups[ngroup];
        std::vector<CComponentTypeItem *> & cmptTypeItems = m_ComponentTypeItems[pComponentTypeGroup];
        idx += (int)cmptTypeItems.size() + 1;//加上Separator
    }
    idx += indexInGroup;
    return idx;
}
CComponentTypeItem * QComboxGroups::GetTypeItemByIndex(int idxcombobox)
{
    if(idxcombobox < 0)
    {
        return nullptr;
    }

    CComponentTypeItem * pItem = nullptr;
    int idx = idxcombobox;
    for(int n = 0; n < (int)m_ComponentTypeGroups.size(); ++n)
    {
        CComponentTypeGroup * pComponentTypeGroup = m_ComponentTypeGroups[n];
        std::vector<CComponentTypeItem *> & cmptTypeItems = m_ComponentTypeItems[pComponentTypeGroup];
        if(idx < (int)cmptTypeItems.size())
        {
            pItem = cmptTypeItems[idx];
            break;
        }
        else
        {
            idx = idx - (int)cmptTypeItems.size() - 1;//Separator
        }
    }

    return pItem;
}


void QComboxGroups::SetDefaultComboBox(const QString& defText, const QIcon &icon)
{
    //信号阻塞
    m_upComboBox->blockSignals(true);

    m_upComboBox->clear();
    if (!icon.isNull())
    {
        QList<QSize> sizes = icon.availableSizes();
        m_upComboBox->setIconSize(QSize(sizes[0].width(), sizes[0].height() + 4)); //上下边界预留2px空白
    }
    m_upComboBox->addItem(icon, defText);
    m_upComboBox->setEnabled(false);

    //取消信号阻塞
    m_upComboBox->blockSignals(false);
}

void QComboxGroups::OnComboBoxChanged()
{
    bool bblock = signalsBlocked();
    const CComponentTypeItem * pCurItem = GetTypeItemByIndex(m_upComboBox->currentIndex());
    emit SelectChangedComponentType(pCurItem);
}

